<?php
declare (strict_types = 1);

namespace app\model;

use think\Model;

/**
 * 菜单模型
 * Class Menu
 * @package app\model
 */
class Menu extends Model
{
    // 表名
    protected $name = 'menus';
    
    // 自动时间戳
    protected $autoWriteTimestamp = true;
    
    // 字段类型转换
    protected $type = [
        'id' => 'integer',
        'parent_id' => 'integer',
        'sort' => 'integer',
        'hidden' => 'integer',
        'status' => 'integer',
        'meta' => 'json',
        'created_at' => 'datetime',
        'updated_at' => 'datetime',
    ];
    
    /**
     * 状态获取器
     * @param $value
     * @param $data
     * @return string
     */
    public function getStatusTextAttr($value, $data)
    {
        $status = [0 => '禁用', 1 => '启用'];
        return $status[$data['status']] ?? '未知';
    }
    
    /**
     * 隐藏获取器
     * @param $value
     * @param $data
     * @return string
     */
    public function getHiddenTextAttr($value, $data)
    {
        $hidden = [0 => '显示', 1 => '隐藏'];
        return $hidden[$data['hidden']] ?? '未知';
    }
    
    /**
     * 关联父级菜单
     * @return \think\model\relation\BelongsTo
     */
    public function parent()
    {
        return $this->belongsTo(Menu::class, 'parent_id', 'id');
    }
    
    /**
     * 关联子级菜单
     * @return \think\model\relation\HasMany
     */
    public function children()
    {
        return $this->hasMany(Menu::class, 'parent_id', 'id');
    }
    
    /**
     * 获取菜单树
     * @param array $where
     * @return array
     */
    public static function getTree(array $where = []): array
    {
        $menus = self::where($where)
            ->order('sort', 'asc')
            ->order('id', 'asc')
            ->select()
            ->toArray();
            
        return self::buildTree($menus);
    }
    
    /**
     * 构建菜单树
     * @param array $menus
     * @param int $parentId
     * @return array
     */
    public static function buildTree(array $menus, int $parentId = 0): array
    {
        $tree = [];
        foreach ($menus as $menu) {
            if ($menu['parent_id'] == $parentId) {
                $children = self::buildTree($menus, $menu['id']);
                if ($children) {
                    $menu['children'] = $children;
                }
                $tree[] = $menu;
            }
        }
        return $tree;
    }
    
    /**
     * 获取所有子级菜单ID
     * @param int $id
     * @return array
     */
    public static function getChildrenIds(int $id): array
    {
        $ids = [$id];
        $children = self::where('parent_id', $id)->column('id');
        
        foreach ($children as $childId) {
            $ids = array_merge($ids, self::getChildrenIds($childId));
        }
        
        return array_unique($ids);
    }
    
    /**
     * 格式化为前端路由格式
     * @param array $menus
     * @return array
     */
    public static function formatForRouter(array $menus): array
    {
        $routes = [];
        foreach ($menus as $menu) {
            $route = [
                'path' => $menu['path'],
                'name' => $menu['name'],
                'component' => $menu['component'],
                'meta' => array_merge([
                    'title' => $menu['title'],
                    'icon' => $menu['icon'],
                    'hidden' => (bool)$menu['hidden'],
                ], $menu['meta'] ?? [])
            ];
            
            if (!empty($menu['redirect'])) {
                $route['redirect'] = $menu['redirect'];
            }
            
            if (!empty($menu['children'])) {
                $route['children'] = self::formatForRouter($menu['children']);
            }
            
            $routes[] = $route;
        }
        return $routes;
    }
}